
from read_file import ReadFile
import sys, logging, time
from pathlib import Path
import pandas as pd
from datetime import datetime, timedelta

logging.basicConfig(
    format = "%(asctime)s %(levelname)s:%(name)s: %(message)s",
    level = logging.INFO,
    datefmt = "%H:%M:%S",
    stream = sys.stderr
)
logger = logging.getLogger(__name__)


class CalculateData(ReadFile):

    def __init__(self, main_path, source_name):
        super().__init__(main_path, source_name)
        self._date_max_str = None
        self._date_max = None
        self._date_min_str = None
        self._date_min = None
        self._df_group_daily = pd.DataFrame()
        self._df_group_daily_format = pd.DataFrame()
        self._spend = None
        self._impressions = None
        self._clicks = None
        self._installs = None
        self._num_dev = None
        self._num_login = None
        self._num_tutor = None
        self._num_dev_before_yesterday = None
        self._num_retent_before_yesterday = None
        self._cum_spend = None
        self._cum_num_dev = None
        self._cum_d1_rech_ndev = None
        self._cum_d1_price = None
        self._cum_num_dev_before_yesterday = None
        self._cum_num_retent_before_yesterday = None
        self._cum_num_dev_before_2day = None
        self._cum_num_d3_retent = None
        self._cum_d3_rech_ndev = None
        self._cum_spend_before_2day = None
        self._cum_d3_price = None


    # 删除无用之列
    def drop_columns(self):
        if not self._df_source.empty:
            df_spend_rech_daily = self._df_source.drop(columns=[
                'yearmonth','yearweek','campaignid','adgroup','ad_ct','platform','region','country_cn','creative_no',
                'creative_tag','game','type','name'])
            self._date_max_str = df_spend_rech_daily['dates'].max()
            self._date_max = datetime.strptime(self._date_max_str, '%Y-%m-%d').date()
            self._date_min_str = df_spend_rech_daily['dates'].min()
            self._date_min = datetime.strptime(self._date_min_str, '%Y-%m-%d').date()

            return {'daily': df_spend_rech_daily }
        else:
            logger.info(f'数据源为空！')
            return False

    # 分组保存分日数据
    def group_by_date(self, df_spend_rech_daily) -> None:
        # 按日期分组计算花费、展示、点击、安装数、量级、注册数、次留数、三留数、付费设备数和金额
        self._df_group_daily = df_spend_rech_daily.groupby([
            'dates'])[['spending', 'impressions', 'clicks', 'installs', 'num_dev', 'num_login', 'num_tutor', 
                       'num_retent', 'num_d3_retent', 'd1_rech_ndev', 'd1_price', 'cum_d3_rech_ndev', 'cum_d3_price']].sum()

    # 计算并保存分日指标
    def cal_daily_data(self) -> None:
        if not self._df_group_daily.empty:
            # 按日期分组计算花费、展示、点击、安装数、量级、注册数、次留数、三留数、付费设备数和金额
            df_group_daily = self._df_group_daily.copy()
            # 添加计算列
            df_group_daily['CPI'] = df_group_daily.apply(lambda x: f"${x['spending'] / x['num_dev']:.1f}" if x['num_dev'] else 0,axis=1)
            df_group_daily['rate_clicks'] = df_group_daily.apply(lambda x: f"{x['clicks'] / x['impressions']: .1%}" if x['impressions'] else 0,axis=1)
            df_group_daily['rate_installs'] = df_group_daily.apply(lambda x: f"{x['installs'] / x['clicks']: .1%}" if x['clicks'] else 0,axis=1)
            df_group_daily['rate_login'] = df_group_daily.apply(lambda x: f"{x['num_login'] / x['num_dev']: .1%}" if x['num_dev'] else 0,axis=1)
            df_group_daily['rate_tutor'] = df_group_daily.apply(lambda x: f"{x['num_tutor'] / x['num_dev']: .1%}" if x['num_dev'] else 0,axis=1)
            df_group_daily['rate_retent'] = df_group_daily.apply(lambda x: f"{x['num_retent'] / x['num_dev']: .1%}" if x['num_dev'] else 0,axis=1)
            df_group_daily['rate_d3_retent'] = df_group_daily.apply(lambda x: f"{x['num_d3_retent'] / x['num_dev']: .1%}" if x['num_dev'] else 0,axis=1)
            df_group_daily['rate_d1_rech'] = df_group_daily.apply(lambda x: f"{x['d1_rech_ndev'] / x['num_dev']: .2%}" if x['num_dev'] else 0,axis=1)
            df_group_daily['ROI_d1'] = df_group_daily.apply(lambda x: f"{x['d1_price'] / x['spending']: .2%}" if x['spending'] else 0,axis=1)
            df_group_daily['rate_d3_rech'] = df_group_daily.apply(lambda x: f"{x['cum_d3_rech_ndev'] / x['num_dev']: .2%}" if x['num_dev'] else 0,axis=1)
            df_group_daily['ROI_d3'] = df_group_daily.apply(lambda x: f"{x['cum_d3_price'] / x['spending']: .2%}" if x['spending'] else 0,axis=1)
            df_group_daily['ratio_d3_rech_retent'] = df_group_daily.apply(lambda x: f"{x['cum_d3_rech_ndev'] / x['num_d3_retent']: .1%}" if x['num_d3_retent'] else 0,axis=1)
            df_group_daily['spending'] = df_group_daily['spending'].transform(lambda x: f"${x/1000:.1f}k")
            df_group_daily['num_dev'] = df_group_daily['num_dev'].transform(lambda x: f"{format(x,',')}")
            df_group_daily.reset_index(inplace=True)
            df_group_daily['dates'] = df_group_daily['dates'].transform(lambda x: x[5:])
            self._df_group_daily_format = df_group_daily[[
                'dates','spending','num_dev','CPI','rate_clicks','rate_installs','rate_login','rate_tutor', 
                'rate_retent','rate_d3_retent','rate_d1_rech','ROI_d1','rate_d3_rech','ROI_d3','ratio_d3_rech_retent']]
    
    # 计算昨日数据
    def cal_yesterday_data(self):
        date_max_yesterday = self._date_max - timedelta(days=1)
        if not self._df_group_daily.empty:
            df_group_daily = self._df_group_daily.copy()
            # 计算昨日花费、展示、点击、安装数、量级、注册数、新手完成引导数
            self._spend = df_group_daily.loc[self._date_max_str, 'spending']
            self._impressions = df_group_daily.loc[self._date_max_str, 'impressions']
            self._clicks = df_group_daily.loc[self._date_max_str, 'clicks']
            self._installs = df_group_daily.loc[self._date_max_str, 'installs']
            self._num_dev = df_group_daily.loc[self._date_max_str, 'num_dev']
            self._num_login = df_group_daily.loc[self._date_max_str, 'num_login']
            self._num_tutor = df_group_daily.loc[self._date_max_str, 'num_tutor']
            # 计算前日量级和次留数
            if self._date_min < self._date_max:
                self._num_dev_before_yesterday = df_group_daily.loc[str(date_max_yesterday), 'num_dev']
                self._num_retent_before_yesterday = df_group_daily.loc[str(date_max_yesterday), 'num_retent']
        
    # 计算累计数据
    def cal_cum_data(self):
        date_max_yesterday = self._date_max - timedelta(days=1)
        date_max_before_2day = date_max_yesterday - timedelta(days=1)
        if not self._df_group_daily.empty:
            df_group_daily = self._df_group_daily.copy()
            # 计算累计全部花费、量级
            self._cum_spend = df_group_daily.loc[:,'spending'].sum()
            self._cum_num_dev = df_group_daily.loc[:,'num_dev'].sum()
            # 计算累计首日付费指标
            self._cum_d1_rech_ndev = df_group_daily.loc[:,'d1_rech_ndev'].sum()
            self._cum_d1_price = df_group_daily.loc[:,'d1_price'].sum()
            # 计算前日累计量级和次留数
            self._cum_num_dev_before_yesterday = df_group_daily.loc[self._date_min_str: str(date_max_yesterday), 'num_dev'].sum()
            self._cum_num_retent_before_yesterday = df_group_daily.loc[self._date_min_str: str(date_max_yesterday), 'num_retent'].sum()
            # 计算前二日累计量级和3留数
            if self._date_min <= date_max_before_2day:
                self._cum_num_dev_before_2day = df_group_daily.loc[self._date_min_str: str(date_max_before_2day), 'num_dev'].sum()
                self._cum_num_d3_retent = df_group_daily.loc[self._date_min_str: str(date_max_before_2day), 'num_d3_retent'].sum()
                self._cum_d3_rech_ndev = df_group_daily.loc[self._date_min_str: str(date_max_before_2day), 'cum_d3_rech_ndev'].sum()
                self._cum_spend_before_2day = df_group_daily.loc[self._date_min_str: str(date_max_before_2day), 'spending'].sum()
                self._cum_d3_price = df_group_daily.loc[self._date_min_str: str(date_max_before_2day), 'cum_d3_price'].sum()


def main():
    s0 = time.perf_counter()
    main_path = Path('Y:\广告\【共用】媒介报告\阿语RoS\账户组\【KOH】账户组优化日志\Andy\GS')
    source_name = 'GS_shark'
    cal_data = CalculateData(main_path, source_name)
    cal_data.read_source()
    data = cal_data.drop_columns()
    cal_data.group_by_date(data['daily'])
    cal_data.cal_yesterday_data()
    cal_data.cal_cum_data()
    cal_data.cal_daily_data()
    logger.info(f'总用时{time.perf_counter() - s0: .2f}秒.')
    # print(cal_data._df_group_daily)


if __name__ == '__main__':
    main()
